add section on GtkCList widget, contributed by Stefan Mars
authorBST 1998 Tony Gale <gale@gtk.org>
Thu, 25 Jun 1998 08:57:29 +0000 (08:57 +0000)
committerTony Gale <gale@src.gnome.org>
Thu, 25 Jun 1998 08:57:29 +0000 (08:57 +0000)
Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>

        * docs/gtk_tut.sgml: add section on GtkCList widget, contributed                                       by Stefan Mars <mars@lysator.liu.se>
        * examples/clist/clist.c examples/clist/Makefile: example code
          for GtkCList widget from the Tutorial

ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
docs/gtk_tut.sgml
docs/tutorial/gtk_tut.sgml
examples/clist/Makefile [new file with mode: 0644]
examples/clist/clist.c [new file with mode: 0644]

index 9438fe3c08702cad41d472ba573efebfdac7e290..c0adc681028507126976faa283a9444c505c3cb4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>
+
+       * docs/gtk_tut.sgml: add section on GtkCList widget, contributed
+         by Stefan Mars <mars@lysator.liu.se>
+       * examples/clist/clist.c examples/clist/Makefile: example code
+         for GtkCList widget from the Tutorial
+
 Wed Jun 24 16:38:02 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize
index 9438fe3c08702cad41d472ba573efebfdac7e290..c0adc681028507126976faa283a9444c505c3cb4 100644 (file)
@@ -1,3 +1,10 @@
+Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>
+
+       * docs/gtk_tut.sgml: add section on GtkCList widget, contributed
+         by Stefan Mars <mars@lysator.liu.se>
+       * examples/clist/clist.c examples/clist/Makefile: example code
+         for GtkCList widget from the Tutorial
+
 Wed Jun 24 16:38:02 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize
index 9438fe3c08702cad41d472ba573efebfdac7e290..c0adc681028507126976faa283a9444c505c3cb4 100644 (file)
@@ -1,3 +1,10 @@
+Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>
+
+       * docs/gtk_tut.sgml: add section on GtkCList widget, contributed
+         by Stefan Mars <mars@lysator.liu.se>
+       * examples/clist/clist.c examples/clist/Makefile: example code
+         for GtkCList widget from the Tutorial
+
 Wed Jun 24 16:38:02 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize
index 9438fe3c08702cad41d472ba573efebfdac7e290..c0adc681028507126976faa283a9444c505c3cb4 100644 (file)
@@ -1,3 +1,10 @@
+Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>
+
+       * docs/gtk_tut.sgml: add section on GtkCList widget, contributed
+         by Stefan Mars <mars@lysator.liu.se>
+       * examples/clist/clist.c examples/clist/Makefile: example code
+         for GtkCList widget from the Tutorial
+
 Wed Jun 24 16:38:02 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize
index 9438fe3c08702cad41d472ba573efebfdac7e290..c0adc681028507126976faa283a9444c505c3cb4 100644 (file)
@@ -1,3 +1,10 @@
+Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>
+
+       * docs/gtk_tut.sgml: add section on GtkCList widget, contributed
+         by Stefan Mars <mars@lysator.liu.se>
+       * examples/clist/clist.c examples/clist/Makefile: example code
+         for GtkCList widget from the Tutorial
+
 Wed Jun 24 16:38:02 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize
index 9438fe3c08702cad41d472ba573efebfdac7e290..c0adc681028507126976faa283a9444c505c3cb4 100644 (file)
@@ -1,3 +1,10 @@
+Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>
+
+       * docs/gtk_tut.sgml: add section on GtkCList widget, contributed
+         by Stefan Mars <mars@lysator.liu.se>
+       * examples/clist/clist.c examples/clist/Makefile: example code
+         for GtkCList widget from the Tutorial
+
 Wed Jun 24 16:38:02 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize
index 9438fe3c08702cad41d472ba573efebfdac7e290..c0adc681028507126976faa283a9444c505c3cb4 100644 (file)
@@ -1,3 +1,10 @@
+Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>
+
+       * docs/gtk_tut.sgml: add section on GtkCList widget, contributed
+         by Stefan Mars <mars@lysator.liu.se>
+       * examples/clist/clist.c examples/clist/Makefile: example code
+         for GtkCList widget from the Tutorial
+
 Wed Jun 24 16:38:02 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize
index ba5535225e5f4345101f4b10169274aa219d44d7..fe93a7cbac2030bbbd46d8f01d7b5612c30aedd8 100644 (file)
@@ -10,7 +10,7 @@
                              name="&lt;imain@gtk.org&gt;"></tt>,
 Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
                              name="&lt;gale@gtk.org&gt;"></tt>
-<date>June 2nd, 1998
+<date>June 24th, 1998
 
 <!-- ***************************************************************** -->
 <sect>Introduction
@@ -4374,9 +4374,719 @@ main (int argc, char *argv[])
 }
 /* example-end */
 </verb></tscreen>
-                              
+
 <!-- ***************************************************************** -->
-<sect> List Widgets
+<sect>CList Widget
+<!-- ***************************************************************** -->
+
+<!-- ----------------------------------------------------------------- -->
+<p>
+The GtkCList widget has replaced the GtkList widget (which is still
+available).
+
+The GtkCList widget is a multi-column list widget that is capable of
+handling literally thousands of rows of information. Each column can
+optionally have a title, which itself is optionally active, allowing
+us to bind a function to it's selection.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Creating a GtkCList widget
+<p>
+Creating a GtkCList is quite straightforward, once you have learned about
+widgets in general. It provides the almost standard two ways, that is the
+hard way, and the easy way. But before we create it, there is one thing we
+should figure out beforehand: how many columns should it have?
+
+Not all columns have to be visible and can be used to store data that is
+related to a certain cell in the list.
+
+<tscreen><verb>
+GtkWidget *gtk_clist_new ( gint columns );
+
+GtkWidget *gtk_clist_new_with_titles( gint   columns,
+                                      gchar *titles[] );
+</verb></tscreen>
+
+The first form is very straight forward, the second might require some
+explanation. Each column can have a title associated with it, and this
+title can be a label or a button that reacts when we click on it. If we
+use the second form, we must provide pointers to the title texts, and the
+number of pointers should equal the number of columns specified. Of course
+we can always use the first form, and manually add titles later.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Modes of operation
+<p>
+There are several attributes that can be used to alter the behaviour of
+a GtkCList. First there is
+
+<tscreen><verb>
+void gtk_clist_set_selection_mode( GtkCList         *clist,
+                                   GtkSelectionMode  mode );
+</verb></tscreen>
+
+which, as the name implies, sets the selection mode of the GtkCList. The first
+argument is the GtkCList widget, and the second specifies the cell selection
+mode (they are defined in gtkenums.h). At the time of this writing, the following
+modes are available to us:
+
+<itemize>
+<item> GTK_SELECTION_SINGLE - The selection is either NULL or contains a GList
+pointer for a single selected item.
+
+<item> GTK_SELECTION_BROWSE -  The selection is NULL if the list contains no
+widgets or insensitive ones only, otherwise it contains a GList pointer for
+one GList structure, and therefore exactly one list item.
+
+<item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list items are
+selected or a GList pointer for the first selected item. That in turn points
+to a GList structure for the second selected item and so on. This is currently
+the <bf>default</bf> for the GtkCList widget.
+
+<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
+</itemize>
+
+Others might be added in later revisions of GTK.
+
+Then there is
+
+<tscreen><verb>
+void gtk_clist_set_policy (GtkCList * clist,
+                           GtkPolicyType vscrollbar_policy,
+                           GtkPolicyType hscrollbar_policy);
+</verb></tscreen>
+
+which defines what happens to the scrollbars. The following values are possible
+for both the vertical and the horizontal scrollbar:
+
+<itemize>
+<item> GTK_POLICY_ALWAYS - The scrollbar will always be there.
+
+<item> GTK_POLICY_AUTOMATIC - The scrollbar will be there only when the number
+of items in the GtkCList exceeds the number that can be shown in the widget.
+</itemize>
+
+We can also define what the border of the GtkCList widget should look like. It is
+done through
+
+<tscreen><verb>
+void gtk_clist_set_border( GtkCList      *clist,
+                           GtkShadowType  border );
+</verb></tscreen>
+
+And the possible values for the second argument are
+
+<itemize>
+<item> GTK_SHADOW_NONE
+
+<item> GTK_SHADOW_IN
+
+<item> GTK_SHADOW_OUT
+
+<item> GTK_SHADOW_ETCHED_IN
+
+<item> GTK_SHADOW_ETCHED_OUT
+</itemize>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Working with titles
+<p>
+When you create a GtkCList widget, you will also get a set of title buttons
+automatically. They live in the top of the CList window, and can act either
+as normal buttons that respond to being pressed, or they can be passive,
+in which case they are nothing more than a title. There are four different
+calls that aid us in setting the status of the title buttons.
+
+<tscreen><verb>
+void gtk_clist_column_title_active( GtkCList *clist,
+                                     gint     column );
+
+void gtk_clist_column_title_passive( GtkCList *clist,
+                                     gint      column );
+
+void gtk_clist_column_titles_active( GtkCList *clist );
+
+void gtk_clist_column_titles_passive( GtkCList *clist );
+</verb></tscreen>
+
+An active title is one which acts as a normal button, a passive one is just
+a label. The first two calls above will activate/deactivate the title button
+above the specific column, while the last two calls activate/deactivate all
+title buttons in the supplied clist widget.
+
+But of course there are those cases when we don't want them at all, and so
+they can be hidden and shown at will using the following two calls.
+
+<tscreen><verb>
+void gtk_clist_column_titles_show( GtkCList *clist );
+
+void gtk_clist_column_titles_hide( GtkCList *clist );
+</verb></tscreen>
+
+For titles to be really useful we need a mechanism to set and change them,
+and this is done using
+
+<tscreen><verb>
+void gtk_clist_set_column_title( GtkCList *clist,
+                                 gint      column,
+                                 gchar    *title );
+</verb></tscreen>
+
+Note that only the title of one column can be set at a time, so if all the
+titles are known from the beginning, then I really suggest using
+gtk_clist_new_with_titles (as described above) to set them. Saves you
+coding time, and makes your program smaller. There are some cases where
+getting the job done the manual way is better, and that's when not all
+titles will be text. GtkCList provides us with title buttons that can in fact
+incorporate whole widgets, for example a pixmap. It's all done through
+
+<tscreen><verb>
+void gtk_clist_set_column_widget( GtkCList  *clist,
+                                  gint       column,
+                                  GtkWidget *widget );
+</verb></tscreen>
+
+which should require no special explanation.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Manipulating the list itself
+<p>
+It is possible to change the justification for a column, and it is done through
+
+<tscreen><verb>
+void gtk_clist_set_column_justification( GtkCList         *clist,
+                                         gint              column,
+                                         GtkJustification  justification );
+</verb></tscreen>
+
+The GtkJustification type can take the following values:
+
+<itemize>
+<item>GTK_JUSTIFY_LEFT - The text in the column will begin from the left edge.
+
+<item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the right edge.
+
+<item>GTK_JUSTIFY_CENTER - The text is placed in the center of the column.
+
+<item>GTK_JUSTIFY_FILL - The text will use up all available space in the
+column. It is normally done by inserting extra blank spaces between words
+(or between inidvidual letters of it's a single word). Much in the same way as
+any ordinary WYSIWYG text editor.
+</itemize>
+
+The next function is a very important one, and should be standard in the setup
+of all GtkCList widgets. When the list is created, the width of the various
+columns are chosen to match their titles, and since this is seldom the right
+width we have to set it using
+
+<tscreen><verb>
+void gtk_clist_set_column_width( GtkCList *clist,
+                                 gint      column,
+                                 gint      width );
+</verb></tscreen>
+
+Note that the width is given in pixels and not letters. The same goes for the
+height of the cells in the columns, but as the default value is the height of
+the current font this isn't as critical to the application. Still, it is done through
+
+<tscreen><verb>
+void gtk_clist_set_row_height( GtkCList *clist,
+                               gint      height );
+</verb></tscreen>
+
+Again, note that the height is given in pixels.
+
+We can also move the list around without user interaction, however, it does
+require that we know what we are looking for. Or in other words, we need the row
+and column of the item we want to scroll to.
+
+<tscreen><verb>
+void gtk_clist_moveto( GtkCList *clist,
+                       gint      row,
+                       gint      column,
+                       gfloat    row_align,
+                       gfloat    col_align );
+</verb></tscreen>
+
+The gfloat row_align is pretty important to understand. It's a value between 0.0 and
+1.0, where 0.0 means that we should scroll the list so the row appears at the top,
+while if the value of row_align is 1.0, the row will appear at the bottom instead. All
+other values between 0.0 and 1.0 are also valid and will place the row between the top
+and the bottom. The last argument, gfloat col_align works in the same way, though 0.0
+marks left and 1.0 marks right instead.
+
+Depending on the application's needs, we don't have to scroll to an item that is
+already visible to us. So how do we know if it is visible? As usual, there is a function
+to find that out as well.
+
+<tscreen><verb>
+GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
+                                        gint      row );
+</verb></tscreen>
+
+The return value is is one of the following:
+
+<itemize>
+<item>GTK_VISIBILITY_NONE
+
+<item>GTK_VISIBILITY_PARTIAL
+
+<item>GTK_VISIBILITY_FULL
+</itemize>
+
+Note that it will only tell us if a row is visible. Currently there is no way to
+determine this for a column. We can get partial information though, because if
+the return is GTK_VISIBILITY_PARTIAL, then some of it is hidden, but we don't know if
+it is the row that is being cut by the lower edge of the listbox, or if the row has
+columns that are outside.
+
+We can also change both the foreground and background colors of a particular
+row. This is useful for marking the row selected by the user, and the two functions
+that is used to do it are
+
+<tscreen><verb>
+void gtk_clist_set_foreground( GtkCList *clist,
+                               gint      row,
+                               GdkColor *color );
+
+void gtk_clist_set_background( GtkCList *clist,
+                               gint      row,
+                               GdkColor *color );
+</verb></tscreen>
+
+Please note that the colors must have been previously allocated.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Adding rows to the list
+<p>
+We can add rows in two ways. They can be appended at the end to the list using
+
+<tscreen><verb>
+gint gtk_clist_append( GtkCList *clist,
+                       gchar    *text[] );
+</verb></tscreen>
+
+or we can insert a row at a given place using
+
+<tscreen><verb>
+void gtk_clist_insert( GtkCList *clist,
+                       gint      row,
+                       gchar    *text[] );
+</verb></tscreen>
+
+In both calls we have to provide a collection of pointers that are the texts
+we want to put in the columns. The number of pointers should equal the number
+of columns in the list. If the text[] argument is NULL, then there will be no
+text in the columns of the row. This is useful, for example,  if we want to
+add pixmaps instead (something that has to be done manually).
+
+Also, please note that the numbering of both rows and columns start at 0.
+
+To remove an individual row we use
+
+<tscreen><verb>
+void gtk_clist_remove( GtkCList *clist,
+                       gint      row );
+</verb></tscreen>
+
+There is also a call that removes all rows in the list. This is a lot faster
+than calling gtk_clist_remove once for each row, which is the only alternative.
+
+<tscreen><verb>
+void gtk_clist_clear( GtkCList *clist );
+</verb></tscreen>
+
+There are also two convenience functions that should be used when a lot of
+changes have to be made to the list. This is to prevent the list flickering while
+being repeatedly updated, which may be highly annoying to the user. So instead it
+is a good idea to freeze the list, do the updates to it, and finally thaw it which
+causes the list to be updated on the screen.
+
+<tscreen><verb>
+void gtk_clist_freeze( GtkCList * clist );
+
+void gtk_clist_thaw( GtkCList * clist );
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Setting text and pixmaps in the cells
+<p>
+A cell can contain a pixmap, text or both. To set them the following
+functions are used.
+
+<tscreen><verb>
+void gtk_clist_set_text( GtkCList *clist,
+                         gint      row,
+                         gint      column,
+                         gchar    *text );
+
+void gtk_clist_set_pixmap( GtkCList  *clist,
+                           gint       row,
+                           gint       column,
+                           GdkPixmap *pixmap,
+                           GdkBitmap *mask );
+
+void gtk_clist_set_pixtext( GtkCList  *clist,
+                            gint       row,
+                            gint       column,
+                            gchar     *text,
+                            guint8     spacing,
+                            GdkPixmap *pixmap,
+                            GdkBitmap *mask );
+</verb></tscreen>
+
+It's quite straightforward. All the calls have the GtkCList as the first
+argument, followed by the row and column of the cell, follwed by the data to be
+set. The gint8 spacing argument in gtk_clist_set_pixtext is the number of pixels
+between the pixmap and the beginning of the text.
+
+To read back the data, we instead use
+
+<tscreen><verb>
+gint gtk_clist_get_text( GtkCList  *clist,
+                         gint       row,
+                         gint       column,
+                         gchar    **text );
+
+gint gtk_clist_get_pixmap( GtkCList   *clist,
+                           gint        row,
+                           gint        column,
+                           GdkPixmap **pixmap,
+                           GdkBitmap **mask );
+
+gint gtk_clist_get_pixtext( GtkCList   *clist,
+                            gint        row,
+                            gint        column,
+                            gchar     **text,
+                            guint8     *spacing,
+                            GdkPixmap **pixmap,
+                            GdkBitmap **mask );
+</verb></tscreen>
+
+It isn't necessary to read it all back in case you aren't interested. Any
+of the pointers that are meant for return values (all except the clist) can
+be NULL. So if we want to read back only the text from a cell that is of
+type pixtext, then we would do the following, assuming that clist, row and
+column already exist:
+
+<tscreen><verb>
+gchar *mytext;
+
+gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
+</verb></tscreen>
+
+There is one more call that is related to what's inside a cell in the
+clist, and that's
+
+<tscreen><verb>
+GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
+                                     gint      row,
+                                     gint      column );
+</verb></tscreen>
+
+which returns the type of data in a cell. The return value is one of
+
+<itemize>
+<item>GTK_CELL_EMPTY
+
+<item>GTK_CELL_TEXT
+
+<item>GTK_CELL_PIXMAP
+
+<item>GTK_CELL_PIXTEXT
+
+<item>GTK_CELL_WIDGET
+</itemize>
+
+There is also a function that will let us set the indentation, both
+vertical and horizontal, of a cell. The indentation value is of type gint,
+given in pixels, and can be both positive and negative.
+
+<tscreen><verb>
+void gtk_clist_set_shift( GtkCList *clist,
+                          gint      row,
+                          gint      column,
+                          gint      vertical,
+                          gint      horizontal );
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Storing data pointers
+<p>
+With a GtkCList it is possible to set a data pointer for a row. This
+pointer will not be visible for the user, but is merely a convinience for
+the programmer to associate a row with a pointer to some additional data.
+
+The functions should be fairly self-explanatory by now
+
+<tscreen><verb>
+void gtk_clist_set_row_data( GtkCList *clist,
+                             gint      row,
+                             gpointer  data );
+
+void gtk_clist_set_row_data_full( GtkCList         *clist,
+                                  gint              row,
+                                  gpointer          data,
+                                  GtkDestroyNotify  destroy );
+
+gpointer gtk_clist_get_row_data( GtkCList *clist,
+                                 gint      row );
+
+gint gtk_clist_find_row_from_data( GtkCList *clist,
+                                   gpointer  data );
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Working with selections
+<p>
+There are also functions available that let us force the (un)selection
+of a row. These are
+
+<tscreen><verb>
+void gtk_clist_select_row( GtkCList *clist,
+                           gint      row,
+                           gint      column );
+
+void gtk_clist_unselect_row( GtkCList *clist,
+                             gint      row,
+                             gint      column );
+</verb></tscreen>
+
+And also a function that will take x and y coordinates (for example, read from
+the mousepointer), and map that onto the list, returning the
+corresponding row and column.
+
+<tscreen><verb>
+gint gtk_clist_get_selection_info( GtkCList *clist,
+                                   gint      x,
+                                   gint      y,
+                                   gint     *row,
+                                   gint     *column );
+</verb></tscreen>
+
+When we detect something of interest, it might be movement of the pointer, a
+click somewhere in the list, we can read the pointer coordinates and find out
+where in the list the pointer is. Cumbersome? Luckily, there is a more simple way...
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>The signals that bring it together
+<p>
+As with all other widgets, there are a few signals that can be used. The
+GtkCList widget is derived from the GtkContainer widget, and so has all the
+same signals, but also the adds following:
+
+<itemize>
+<item>select_row - This signal will send the following information, in
+order: GtkCList *clist, gint row, gint column, GtkEventButton *event
+
+<item>unselect_row - When the user unselects a row, this signal is activated. It
+sends the same information as select_row
+
+<item>click_column - Send GtkCList *clist, gint column
+</itemize>
+
+So if we want to connect a callback to select_row, the callback function would
+be declared like this
+
+<tscreen><verb>
+void select_row_callback(GtkWidget *widget,
+                         gint row,
+                        gint column,
+                         GdkEventButton *event,
+                        gpointer data);
+</verb></tscreen>
+
+The callback is connected as usual with
+
+<tscreen><verb>
+gtk_signal_connect(GTK_OBJECT( clist),
+                  "select_row"
+                  GTK_SIGNAL_FUNC(select_row_callback),
+                  NULL);
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>A GtkCList example
+<p>
+
+<tscreen><verb>
+/* example-start clist clist.c */
+
+#include        <gtk/gtk.h>
+#include       <glib.h>
+
+/* These are just the prototypes of the various callbacks */
+void button_add_clicked( GtkWidget *button, gpointer data);
+void button_clear_clicked( GtkWidget *button, gpointer data);
+void button_hide_show_clicked( GtkWidget *button, gpointer data);
+void selection_made( GtkWidget *clist, gint row, gint column,
+                    GdkEventButton *event, gpointer data);
+
+gint main (int argc, gchar *argv[])
+{                                  
+    GtkWidget       *window;
+    GtkWidget       *vbox, *hbox;
+    GtkWidget      *clist;
+    GtkWidget      *button_add, *button_clear, *button_hide_show;    
+    gchar          *titles[2] = {"Ingredients","Amount"};
+
+    gtk_init(&amp;argc, &amp;argv);
+    
+    
+    window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
+
+    gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
+    gtk_signal_connect(GTK_OBJECT(window),
+                      "destroy",
+                      GTK_SIGNAL_FUNC(gtk_main_quit),
+                      NULL);
+    
+    vbox=gtk_vbox_new(FALSE, 5);
+    gtk_container_border_width(GTK_CONTAINER(vbox), 5);
+    gtk_container_add(GTK_CONTAINER(window), vbox);
+    gtk_widget_show(vbox);
+    
+    /* Create the GtkCList. For this example we use 2 columns */
+    clist = gtk_clist_new_with_titles( 2, titles);
+
+    /* When a selection is made, we want to know about it. The callback
+     * used is selection_made, and it's code can be found further down */
+    gtk_signal_connect(GTK_OBJECT(clist), "select_row",
+                      GTK_SIGNAL_FUNC(selection_made),
+                      NULL);
+
+    /* It isn't necessary to shadow the border, but it looks nice :) */
+    gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT);
+
+    /* What however is important, is that we set the column widths as
+     * they will never be right otherwise. Note that the columns are
+     * numbered from 0 and up (to 1 in this case).
+     */
+    gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
+
+    /* Scollbars _only when needed_ */
+    gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC,
+                                          GTK_POLICY_AUTOMATIC);
+
+    /* Add the GtkCList widget to the vertical box and show it. */
+    gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
+    gtk_widget_show(clist);
+
+    /* Create the buttons and add them to the window. See the button
+     * tutorial for more examples and comments on this.
+     */
+    hbox = gtk_hbox_new(FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+    gtk_widget_show(hbox);
+
+    button_add = gtk_button_new_with_label("Add List");
+    button_clear = gtk_button_new_with_label("Clear List");
+    button_hide_show = gtk_button_new_with_label("Hide/Show titles");
+
+    gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
+
+    /* Connect our callbacks to the three buttons */
+    gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
+                             GTK_SIGNAL_FUNC(button_add_clicked),
+                             (gpointer) clist);
+    gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
+                             GTK_SIGNAL_FUNC(button_clear_clicked),
+                             (gpointer) clist);
+    gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
+                             GTK_SIGNAL_FUNC(button_hide_show_clicked),
+                             (gpointer) clist);
+
+    gtk_widget_show(button_add);
+    gtk_widget_show(button_clear);
+    gtk_widget_show(button_hide_show);
+
+    /* The interface is completely set up so we show the window and
+     * enter the gtk_main loop.
+     */
+    gtk_widget_show(window);
+    gtk_main();
+    
+    return 0;
+}
+
+/* User clicked the "Add List" button. */
+void button_add_clicked( GtkWidget *button, gpointer data)
+{
+    int                indx;
+
+    /* Something silly to add to the list. 4 rows of 2 columns each */
+    gchar      *drink[4][2] = {{"Milk", "3 Oz"},
+                              {"Water", "6 l"},
+                              {"Carrots", "2"},
+                              {"Snakes", "55"}};
+
+    /* Here we do the actual adding of the text. It's done once for
+     * each row.
+     */
+    for( indx=0; indx < 4; indx++)
+       gtk_clist_append( (GtkCList*) data, drink[indx]);
+
+    return;
+}
+
+/* User clicked the "Clear List" button. */
+void button_clear_clicked( GtkWidget *button, gpointer data)
+{
+    /* Clear the list using gtk_clist_clear. This is much faster than
+     * calling gtk_clist_remove once for each row.
+     */
+    gtk_clist_clear((GtkCList*) data);
+
+    return;
+}
+
+/* The user clicked the "Hide/Show titles" button. */
+void button_hide_show_clicked( GtkWidget *button, gpointer data)
+{
+    /* Just a flag to remember the status. 0 = currently visible */
+    static short int flag = 0;
+
+    if (flag == 0)
+    {
+        /* Hide the titles and set the flag to 1 */
+       gtk_clist_column_titles_hide((GtkCList*) data);
+       flag++;
+    }
+    else
+    {
+        /* Show the titles and reset flag to 0 */
+       gtk_clist_column_titles_show((GtkCList*) data);
+       flag--;
+    }
+
+    return;
+}
+
+/* If we come here, then the user has selected a row in the list. */
+void selection_made( GtkWidget *clist, gint row, gint column,
+                    GdkEventButton *event, gpointer data)
+{
+    gchar      *text;
+
+    /* Get the text that is stored in the selected row and column
+     * which was clicked in. We will receive it as a pointer in the
+     * argument text.
+     */
+    gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
+
+    /* Just prints some information about the selected row */
+    g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text);
+
+    return;
+}
+/* example-end */
+</verb></tscreen>
+                    
+<!-- ***************************************************************** -->
+<sect> List Widget
 <!-- ***************************************************************** -->
 <p>
 NOTE: The GtkList widget has been superseded by the GtkCList widget.
@@ -5879,9 +6589,6 @@ from your time.
 <sect1> Fixed Container
 <p>
 <!-- ----------------------------------------------------------------- -->
-<sect1> CList
-<p>
-<!-- ----------------------------------------------------------------- -->
 <sect1> Range Controls
 <p>
 <!-- ----------------------------------------------------------------- -->
@@ -6557,6 +7264,8 @@ void input_callback( gpointer          data,
                      GdkInputCondition condition );
 </verb></tscreen>
 
+Where <tt/source/ and <tt/condition/ are as specified above.
+
 <!-- ----------------------------------------------------------------- -->
 <sect1>Idle Functions
 <p>
index ba5535225e5f4345101f4b10169274aa219d44d7..fe93a7cbac2030bbbd46d8f01d7b5612c30aedd8 100644 (file)
@@ -10,7 +10,7 @@
                              name="&lt;imain@gtk.org&gt;"></tt>,
 Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
                              name="&lt;gale@gtk.org&gt;"></tt>
-<date>June 2nd, 1998
+<date>June 24th, 1998
 
 <!-- ***************************************************************** -->
 <sect>Introduction
@@ -4374,9 +4374,719 @@ main (int argc, char *argv[])
 }
 /* example-end */
 </verb></tscreen>
-                              
+
 <!-- ***************************************************************** -->
-<sect> List Widgets
+<sect>CList Widget
+<!-- ***************************************************************** -->
+
+<!-- ----------------------------------------------------------------- -->
+<p>
+The GtkCList widget has replaced the GtkList widget (which is still
+available).
+
+The GtkCList widget is a multi-column list widget that is capable of
+handling literally thousands of rows of information. Each column can
+optionally have a title, which itself is optionally active, allowing
+us to bind a function to it's selection.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Creating a GtkCList widget
+<p>
+Creating a GtkCList is quite straightforward, once you have learned about
+widgets in general. It provides the almost standard two ways, that is the
+hard way, and the easy way. But before we create it, there is one thing we
+should figure out beforehand: how many columns should it have?
+
+Not all columns have to be visible and can be used to store data that is
+related to a certain cell in the list.
+
+<tscreen><verb>
+GtkWidget *gtk_clist_new ( gint columns );
+
+GtkWidget *gtk_clist_new_with_titles( gint   columns,
+                                      gchar *titles[] );
+</verb></tscreen>
+
+The first form is very straight forward, the second might require some
+explanation. Each column can have a title associated with it, and this
+title can be a label or a button that reacts when we click on it. If we
+use the second form, we must provide pointers to the title texts, and the
+number of pointers should equal the number of columns specified. Of course
+we can always use the first form, and manually add titles later.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Modes of operation
+<p>
+There are several attributes that can be used to alter the behaviour of
+a GtkCList. First there is
+
+<tscreen><verb>
+void gtk_clist_set_selection_mode( GtkCList         *clist,
+                                   GtkSelectionMode  mode );
+</verb></tscreen>
+
+which, as the name implies, sets the selection mode of the GtkCList. The first
+argument is the GtkCList widget, and the second specifies the cell selection
+mode (they are defined in gtkenums.h). At the time of this writing, the following
+modes are available to us:
+
+<itemize>
+<item> GTK_SELECTION_SINGLE - The selection is either NULL or contains a GList
+pointer for a single selected item.
+
+<item> GTK_SELECTION_BROWSE -  The selection is NULL if the list contains no
+widgets or insensitive ones only, otherwise it contains a GList pointer for
+one GList structure, and therefore exactly one list item.
+
+<item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list items are
+selected or a GList pointer for the first selected item. That in turn points
+to a GList structure for the second selected item and so on. This is currently
+the <bf>default</bf> for the GtkCList widget.
+
+<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
+</itemize>
+
+Others might be added in later revisions of GTK.
+
+Then there is
+
+<tscreen><verb>
+void gtk_clist_set_policy (GtkCList * clist,
+                           GtkPolicyType vscrollbar_policy,
+                           GtkPolicyType hscrollbar_policy);
+</verb></tscreen>
+
+which defines what happens to the scrollbars. The following values are possible
+for both the vertical and the horizontal scrollbar:
+
+<itemize>
+<item> GTK_POLICY_ALWAYS - The scrollbar will always be there.
+
+<item> GTK_POLICY_AUTOMATIC - The scrollbar will be there only when the number
+of items in the GtkCList exceeds the number that can be shown in the widget.
+</itemize>
+
+We can also define what the border of the GtkCList widget should look like. It is
+done through
+
+<tscreen><verb>
+void gtk_clist_set_border( GtkCList      *clist,
+                           GtkShadowType  border );
+</verb></tscreen>
+
+And the possible values for the second argument are
+
+<itemize>
+<item> GTK_SHADOW_NONE
+
+<item> GTK_SHADOW_IN
+
+<item> GTK_SHADOW_OUT
+
+<item> GTK_SHADOW_ETCHED_IN
+
+<item> GTK_SHADOW_ETCHED_OUT
+</itemize>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Working with titles
+<p>
+When you create a GtkCList widget, you will also get a set of title buttons
+automatically. They live in the top of the CList window, and can act either
+as normal buttons that respond to being pressed, or they can be passive,
+in which case they are nothing more than a title. There are four different
+calls that aid us in setting the status of the title buttons.
+
+<tscreen><verb>
+void gtk_clist_column_title_active( GtkCList *clist,
+                                     gint     column );
+
+void gtk_clist_column_title_passive( GtkCList *clist,
+                                     gint      column );
+
+void gtk_clist_column_titles_active( GtkCList *clist );
+
+void gtk_clist_column_titles_passive( GtkCList *clist );
+</verb></tscreen>
+
+An active title is one which acts as a normal button, a passive one is just
+a label. The first two calls above will activate/deactivate the title button
+above the specific column, while the last two calls activate/deactivate all
+title buttons in the supplied clist widget.
+
+But of course there are those cases when we don't want them at all, and so
+they can be hidden and shown at will using the following two calls.
+
+<tscreen><verb>
+void gtk_clist_column_titles_show( GtkCList *clist );
+
+void gtk_clist_column_titles_hide( GtkCList *clist );
+</verb></tscreen>
+
+For titles to be really useful we need a mechanism to set and change them,
+and this is done using
+
+<tscreen><verb>
+void gtk_clist_set_column_title( GtkCList *clist,
+                                 gint      column,
+                                 gchar    *title );
+</verb></tscreen>
+
+Note that only the title of one column can be set at a time, so if all the
+titles are known from the beginning, then I really suggest using
+gtk_clist_new_with_titles (as described above) to set them. Saves you
+coding time, and makes your program smaller. There are some cases where
+getting the job done the manual way is better, and that's when not all
+titles will be text. GtkCList provides us with title buttons that can in fact
+incorporate whole widgets, for example a pixmap. It's all done through
+
+<tscreen><verb>
+void gtk_clist_set_column_widget( GtkCList  *clist,
+                                  gint       column,
+                                  GtkWidget *widget );
+</verb></tscreen>
+
+which should require no special explanation.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Manipulating the list itself
+<p>
+It is possible to change the justification for a column, and it is done through
+
+<tscreen><verb>
+void gtk_clist_set_column_justification( GtkCList         *clist,
+                                         gint              column,
+                                         GtkJustification  justification );
+</verb></tscreen>
+
+The GtkJustification type can take the following values:
+
+<itemize>
+<item>GTK_JUSTIFY_LEFT - The text in the column will begin from the left edge.
+
+<item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the right edge.
+
+<item>GTK_JUSTIFY_CENTER - The text is placed in the center of the column.
+
+<item>GTK_JUSTIFY_FILL - The text will use up all available space in the
+column. It is normally done by inserting extra blank spaces between words
+(or between inidvidual letters of it's a single word). Much in the same way as
+any ordinary WYSIWYG text editor.
+</itemize>
+
+The next function is a very important one, and should be standard in the setup
+of all GtkCList widgets. When the list is created, the width of the various
+columns are chosen to match their titles, and since this is seldom the right
+width we have to set it using
+
+<tscreen><verb>
+void gtk_clist_set_column_width( GtkCList *clist,
+                                 gint      column,
+                                 gint      width );
+</verb></tscreen>
+
+Note that the width is given in pixels and not letters. The same goes for the
+height of the cells in the columns, but as the default value is the height of
+the current font this isn't as critical to the application. Still, it is done through
+
+<tscreen><verb>
+void gtk_clist_set_row_height( GtkCList *clist,
+                               gint      height );
+</verb></tscreen>
+
+Again, note that the height is given in pixels.
+
+We can also move the list around without user interaction, however, it does
+require that we know what we are looking for. Or in other words, we need the row
+and column of the item we want to scroll to.
+
+<tscreen><verb>
+void gtk_clist_moveto( GtkCList *clist,
+                       gint      row,
+                       gint      column,
+                       gfloat    row_align,
+                       gfloat    col_align );
+</verb></tscreen>
+
+The gfloat row_align is pretty important to understand. It's a value between 0.0 and
+1.0, where 0.0 means that we should scroll the list so the row appears at the top,
+while if the value of row_align is 1.0, the row will appear at the bottom instead. All
+other values between 0.0 and 1.0 are also valid and will place the row between the top
+and the bottom. The last argument, gfloat col_align works in the same way, though 0.0
+marks left and 1.0 marks right instead.
+
+Depending on the application's needs, we don't have to scroll to an item that is
+already visible to us. So how do we know if it is visible? As usual, there is a function
+to find that out as well.
+
+<tscreen><verb>
+GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
+                                        gint      row );
+</verb></tscreen>
+
+The return value is is one of the following:
+
+<itemize>
+<item>GTK_VISIBILITY_NONE
+
+<item>GTK_VISIBILITY_PARTIAL
+
+<item>GTK_VISIBILITY_FULL
+</itemize>
+
+Note that it will only tell us if a row is visible. Currently there is no way to
+determine this for a column. We can get partial information though, because if
+the return is GTK_VISIBILITY_PARTIAL, then some of it is hidden, but we don't know if
+it is the row that is being cut by the lower edge of the listbox, or if the row has
+columns that are outside.
+
+We can also change both the foreground and background colors of a particular
+row. This is useful for marking the row selected by the user, and the two functions
+that is used to do it are
+
+<tscreen><verb>
+void gtk_clist_set_foreground( GtkCList *clist,
+                               gint      row,
+                               GdkColor *color );
+
+void gtk_clist_set_background( GtkCList *clist,
+                               gint      row,
+                               GdkColor *color );
+</verb></tscreen>
+
+Please note that the colors must have been previously allocated.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Adding rows to the list
+<p>
+We can add rows in two ways. They can be appended at the end to the list using
+
+<tscreen><verb>
+gint gtk_clist_append( GtkCList *clist,
+                       gchar    *text[] );
+</verb></tscreen>
+
+or we can insert a row at a given place using
+
+<tscreen><verb>
+void gtk_clist_insert( GtkCList *clist,
+                       gint      row,
+                       gchar    *text[] );
+</verb></tscreen>
+
+In both calls we have to provide a collection of pointers that are the texts
+we want to put in the columns. The number of pointers should equal the number
+of columns in the list. If the text[] argument is NULL, then there will be no
+text in the columns of the row. This is useful, for example,  if we want to
+add pixmaps instead (something that has to be done manually).
+
+Also, please note that the numbering of both rows and columns start at 0.
+
+To remove an individual row we use
+
+<tscreen><verb>
+void gtk_clist_remove( GtkCList *clist,
+                       gint      row );
+</verb></tscreen>
+
+There is also a call that removes all rows in the list. This is a lot faster
+than calling gtk_clist_remove once for each row, which is the only alternative.
+
+<tscreen><verb>
+void gtk_clist_clear( GtkCList *clist );
+</verb></tscreen>
+
+There are also two convenience functions that should be used when a lot of
+changes have to be made to the list. This is to prevent the list flickering while
+being repeatedly updated, which may be highly annoying to the user. So instead it
+is a good idea to freeze the list, do the updates to it, and finally thaw it which
+causes the list to be updated on the screen.
+
+<tscreen><verb>
+void gtk_clist_freeze( GtkCList * clist );
+
+void gtk_clist_thaw( GtkCList * clist );
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Setting text and pixmaps in the cells
+<p>
+A cell can contain a pixmap, text or both. To set them the following
+functions are used.
+
+<tscreen><verb>
+void gtk_clist_set_text( GtkCList *clist,
+                         gint      row,
+                         gint      column,
+                         gchar    *text );
+
+void gtk_clist_set_pixmap( GtkCList  *clist,
+                           gint       row,
+                           gint       column,
+                           GdkPixmap *pixmap,
+                           GdkBitmap *mask );
+
+void gtk_clist_set_pixtext( GtkCList  *clist,
+                            gint       row,
+                            gint       column,
+                            gchar     *text,
+                            guint8     spacing,
+                            GdkPixmap *pixmap,
+                            GdkBitmap *mask );
+</verb></tscreen>
+
+It's quite straightforward. All the calls have the GtkCList as the first
+argument, followed by the row and column of the cell, follwed by the data to be
+set. The gint8 spacing argument in gtk_clist_set_pixtext is the number of pixels
+between the pixmap and the beginning of the text.
+
+To read back the data, we instead use
+
+<tscreen><verb>
+gint gtk_clist_get_text( GtkCList  *clist,
+                         gint       row,
+                         gint       column,
+                         gchar    **text );
+
+gint gtk_clist_get_pixmap( GtkCList   *clist,
+                           gint        row,
+                           gint        column,
+                           GdkPixmap **pixmap,
+                           GdkBitmap **mask );
+
+gint gtk_clist_get_pixtext( GtkCList   *clist,
+                            gint        row,
+                            gint        column,
+                            gchar     **text,
+                            guint8     *spacing,
+                            GdkPixmap **pixmap,
+                            GdkBitmap **mask );
+</verb></tscreen>
+
+It isn't necessary to read it all back in case you aren't interested. Any
+of the pointers that are meant for return values (all except the clist) can
+be NULL. So if we want to read back only the text from a cell that is of
+type pixtext, then we would do the following, assuming that clist, row and
+column already exist:
+
+<tscreen><verb>
+gchar *mytext;
+
+gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
+</verb></tscreen>
+
+There is one more call that is related to what's inside a cell in the
+clist, and that's
+
+<tscreen><verb>
+GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
+                                     gint      row,
+                                     gint      column );
+</verb></tscreen>
+
+which returns the type of data in a cell. The return value is one of
+
+<itemize>
+<item>GTK_CELL_EMPTY
+
+<item>GTK_CELL_TEXT
+
+<item>GTK_CELL_PIXMAP
+
+<item>GTK_CELL_PIXTEXT
+
+<item>GTK_CELL_WIDGET
+</itemize>
+
+There is also a function that will let us set the indentation, both
+vertical and horizontal, of a cell. The indentation value is of type gint,
+given in pixels, and can be both positive and negative.
+
+<tscreen><verb>
+void gtk_clist_set_shift( GtkCList *clist,
+                          gint      row,
+                          gint      column,
+                          gint      vertical,
+                          gint      horizontal );
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Storing data pointers
+<p>
+With a GtkCList it is possible to set a data pointer for a row. This
+pointer will not be visible for the user, but is merely a convinience for
+the programmer to associate a row with a pointer to some additional data.
+
+The functions should be fairly self-explanatory by now
+
+<tscreen><verb>
+void gtk_clist_set_row_data( GtkCList *clist,
+                             gint      row,
+                             gpointer  data );
+
+void gtk_clist_set_row_data_full( GtkCList         *clist,
+                                  gint              row,
+                                  gpointer          data,
+                                  GtkDestroyNotify  destroy );
+
+gpointer gtk_clist_get_row_data( GtkCList *clist,
+                                 gint      row );
+
+gint gtk_clist_find_row_from_data( GtkCList *clist,
+                                   gpointer  data );
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Working with selections
+<p>
+There are also functions available that let us force the (un)selection
+of a row. These are
+
+<tscreen><verb>
+void gtk_clist_select_row( GtkCList *clist,
+                           gint      row,
+                           gint      column );
+
+void gtk_clist_unselect_row( GtkCList *clist,
+                             gint      row,
+                             gint      column );
+</verb></tscreen>
+
+And also a function that will take x and y coordinates (for example, read from
+the mousepointer), and map that onto the list, returning the
+corresponding row and column.
+
+<tscreen><verb>
+gint gtk_clist_get_selection_info( GtkCList *clist,
+                                   gint      x,
+                                   gint      y,
+                                   gint     *row,
+                                   gint     *column );
+</verb></tscreen>
+
+When we detect something of interest, it might be movement of the pointer, a
+click somewhere in the list, we can read the pointer coordinates and find out
+where in the list the pointer is. Cumbersome? Luckily, there is a more simple way...
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>The signals that bring it together
+<p>
+As with all other widgets, there are a few signals that can be used. The
+GtkCList widget is derived from the GtkContainer widget, and so has all the
+same signals, but also the adds following:
+
+<itemize>
+<item>select_row - This signal will send the following information, in
+order: GtkCList *clist, gint row, gint column, GtkEventButton *event
+
+<item>unselect_row - When the user unselects a row, this signal is activated. It
+sends the same information as select_row
+
+<item>click_column - Send GtkCList *clist, gint column
+</itemize>
+
+So if we want to connect a callback to select_row, the callback function would
+be declared like this
+
+<tscreen><verb>
+void select_row_callback(GtkWidget *widget,
+                         gint row,
+                        gint column,
+                         GdkEventButton *event,
+                        gpointer data);
+</verb></tscreen>
+
+The callback is connected as usual with
+
+<tscreen><verb>
+gtk_signal_connect(GTK_OBJECT( clist),
+                  "select_row"
+                  GTK_SIGNAL_FUNC(select_row_callback),
+                  NULL);
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>A GtkCList example
+<p>
+
+<tscreen><verb>
+/* example-start clist clist.c */
+
+#include        <gtk/gtk.h>
+#include       <glib.h>
+
+/* These are just the prototypes of the various callbacks */
+void button_add_clicked( GtkWidget *button, gpointer data);
+void button_clear_clicked( GtkWidget *button, gpointer data);
+void button_hide_show_clicked( GtkWidget *button, gpointer data);
+void selection_made( GtkWidget *clist, gint row, gint column,
+                    GdkEventButton *event, gpointer data);
+
+gint main (int argc, gchar *argv[])
+{                                  
+    GtkWidget       *window;
+    GtkWidget       *vbox, *hbox;
+    GtkWidget      *clist;
+    GtkWidget      *button_add, *button_clear, *button_hide_show;    
+    gchar          *titles[2] = {"Ingredients","Amount"};
+
+    gtk_init(&amp;argc, &amp;argv);
+    
+    
+    window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
+
+    gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
+    gtk_signal_connect(GTK_OBJECT(window),
+                      "destroy",
+                      GTK_SIGNAL_FUNC(gtk_main_quit),
+                      NULL);
+    
+    vbox=gtk_vbox_new(FALSE, 5);
+    gtk_container_border_width(GTK_CONTAINER(vbox), 5);
+    gtk_container_add(GTK_CONTAINER(window), vbox);
+    gtk_widget_show(vbox);
+    
+    /* Create the GtkCList. For this example we use 2 columns */
+    clist = gtk_clist_new_with_titles( 2, titles);
+
+    /* When a selection is made, we want to know about it. The callback
+     * used is selection_made, and it's code can be found further down */
+    gtk_signal_connect(GTK_OBJECT(clist), "select_row",
+                      GTK_SIGNAL_FUNC(selection_made),
+                      NULL);
+
+    /* It isn't necessary to shadow the border, but it looks nice :) */
+    gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT);
+
+    /* What however is important, is that we set the column widths as
+     * they will never be right otherwise. Note that the columns are
+     * numbered from 0 and up (to 1 in this case).
+     */
+    gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
+
+    /* Scollbars _only when needed_ */
+    gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC,
+                                          GTK_POLICY_AUTOMATIC);
+
+    /* Add the GtkCList widget to the vertical box and show it. */
+    gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
+    gtk_widget_show(clist);
+
+    /* Create the buttons and add them to the window. See the button
+     * tutorial for more examples and comments on this.
+     */
+    hbox = gtk_hbox_new(FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+    gtk_widget_show(hbox);
+
+    button_add = gtk_button_new_with_label("Add List");
+    button_clear = gtk_button_new_with_label("Clear List");
+    button_hide_show = gtk_button_new_with_label("Hide/Show titles");
+
+    gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
+
+    /* Connect our callbacks to the three buttons */
+    gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
+                             GTK_SIGNAL_FUNC(button_add_clicked),
+                             (gpointer) clist);
+    gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
+                             GTK_SIGNAL_FUNC(button_clear_clicked),
+                             (gpointer) clist);
+    gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
+                             GTK_SIGNAL_FUNC(button_hide_show_clicked),
+                             (gpointer) clist);
+
+    gtk_widget_show(button_add);
+    gtk_widget_show(button_clear);
+    gtk_widget_show(button_hide_show);
+
+    /* The interface is completely set up so we show the window and
+     * enter the gtk_main loop.
+     */
+    gtk_widget_show(window);
+    gtk_main();
+    
+    return 0;
+}
+
+/* User clicked the "Add List" button. */
+void button_add_clicked( GtkWidget *button, gpointer data)
+{
+    int                indx;
+
+    /* Something silly to add to the list. 4 rows of 2 columns each */
+    gchar      *drink[4][2] = {{"Milk", "3 Oz"},
+                              {"Water", "6 l"},
+                              {"Carrots", "2"},
+                              {"Snakes", "55"}};
+
+    /* Here we do the actual adding of the text. It's done once for
+     * each row.
+     */
+    for( indx=0; indx < 4; indx++)
+       gtk_clist_append( (GtkCList*) data, drink[indx]);
+
+    return;
+}
+
+/* User clicked the "Clear List" button. */
+void button_clear_clicked( GtkWidget *button, gpointer data)
+{
+    /* Clear the list using gtk_clist_clear. This is much faster than
+     * calling gtk_clist_remove once for each row.
+     */
+    gtk_clist_clear((GtkCList*) data);
+
+    return;
+}
+
+/* The user clicked the "Hide/Show titles" button. */
+void button_hide_show_clicked( GtkWidget *button, gpointer data)
+{
+    /* Just a flag to remember the status. 0 = currently visible */
+    static short int flag = 0;
+
+    if (flag == 0)
+    {
+        /* Hide the titles and set the flag to 1 */
+       gtk_clist_column_titles_hide((GtkCList*) data);
+       flag++;
+    }
+    else
+    {
+        /* Show the titles and reset flag to 0 */
+       gtk_clist_column_titles_show((GtkCList*) data);
+       flag--;
+    }
+
+    return;
+}
+
+/* If we come here, then the user has selected a row in the list. */
+void selection_made( GtkWidget *clist, gint row, gint column,
+                    GdkEventButton *event, gpointer data)
+{
+    gchar      *text;
+
+    /* Get the text that is stored in the selected row and column
+     * which was clicked in. We will receive it as a pointer in the
+     * argument text.
+     */
+    gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
+
+    /* Just prints some information about the selected row */
+    g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text);
+
+    return;
+}
+/* example-end */
+</verb></tscreen>
+                    
+<!-- ***************************************************************** -->
+<sect> List Widget
 <!-- ***************************************************************** -->
 <p>
 NOTE: The GtkList widget has been superseded by the GtkCList widget.
@@ -5879,9 +6589,6 @@ from your time.
 <sect1> Fixed Container
 <p>
 <!-- ----------------------------------------------------------------- -->
-<sect1> CList
-<p>
-<!-- ----------------------------------------------------------------- -->
 <sect1> Range Controls
 <p>
 <!-- ----------------------------------------------------------------- -->
@@ -6557,6 +7264,8 @@ void input_callback( gpointer          data,
                      GdkInputCondition condition );
 </verb></tscreen>
 
+Where <tt/source/ and <tt/condition/ are as specified above.
+
 <!-- ----------------------------------------------------------------- -->
 <sect1>Idle Functions
 <p>
diff --git a/examples/clist/Makefile b/examples/clist/Makefile
new file mode 100644 (file)
index 0000000..d9836f7
--- /dev/null
@@ -0,0 +1,8 @@
+
+CC = gcc
+
+clist: clist.c 
+       $(CC) `gtk-config --cflags` `gtk-config --libs` clist.c -o clist
+
+clean: 
+       rm -f *.o clist
diff --git a/examples/clist/clist.c b/examples/clist/clist.c
new file mode 100644 (file)
index 0000000..2d766a1
--- /dev/null
@@ -0,0 +1,173 @@
+/* example-start clist clist.c */
+
+#include        <gtk/gtk.h>
+#include       <glib.h>
+
+/* These are just the prototypes of the various callbacks */
+void button_add_clicked( GtkWidget *button, gpointer data);
+void button_clear_clicked( GtkWidget *button, gpointer data);
+void button_hide_show_clicked( GtkWidget *button, gpointer data);
+void selection_made( GtkWidget *clist, gint row, gint column,
+                    GdkEventButton *event, gpointer data);
+
+gint main (int argc, gchar *argv[])
+{                                  
+    GtkWidget       *window;
+    GtkWidget       *vbox, *hbox;
+    GtkWidget      *clist;
+    GtkWidget      *button_add, *button_clear, *button_hide_show;    
+    gchar          *titles[2] = {"Ingredients","Amount"};
+
+    gtk_init(&argc, &argv);
+    
+    
+    window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
+
+    gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
+    gtk_signal_connect(GTK_OBJECT(window),
+                      "destroy",
+                      GTK_SIGNAL_FUNC(gtk_main_quit),
+                      NULL);
+    
+    vbox=gtk_vbox_new(FALSE, 5);
+    gtk_container_border_width(GTK_CONTAINER(vbox), 5);
+    gtk_container_add(GTK_CONTAINER(window), vbox);
+    gtk_widget_show(vbox);
+    
+    /* Create the GtkCList. For this example we use 2 columns */
+    clist = gtk_clist_new_with_titles( 2, titles);
+
+    /* When a selection is made, we want to know about it. The callback
+     * used is selection_made, and it's code can be found further down */
+    gtk_signal_connect(GTK_OBJECT(clist), "select_row",
+                      GTK_SIGNAL_FUNC(selection_made),
+                      NULL);
+
+    /* It isn't necessary to shadow the border, but it looks nice :) */
+    gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT);
+
+    /* What however is important, is that we set the column widths as
+     * they will never be right otherwise. Note that the columns are
+     * numbered from 0 and up (to 1 in this case).
+     */
+    gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
+
+    /* Scollbars _only when needed_ */
+    gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC,
+                                          GTK_POLICY_AUTOMATIC);
+
+    /* Add the GtkCList widget to the vertical box and show it. */
+    gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
+    gtk_widget_show(clist);
+
+    /* Create the buttons and add them to the window. See the button
+     * tutorial for more examples and comments on this.
+     */
+    hbox = gtk_hbox_new(FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+    gtk_widget_show(hbox);
+
+    button_add = gtk_button_new_with_label("Add List");
+    button_clear = gtk_button_new_with_label("Clear List");
+    button_hide_show = gtk_button_new_with_label("Hide/Show titles");
+
+    gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
+
+    /* Connect our callbacks to the three buttons */
+    gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
+                             GTK_SIGNAL_FUNC(button_add_clicked),
+                             (gpointer) clist);
+    gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
+                             GTK_SIGNAL_FUNC(button_clear_clicked),
+                             (gpointer) clist);
+    gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
+                             GTK_SIGNAL_FUNC(button_hide_show_clicked),
+                             (gpointer) clist);
+
+    gtk_widget_show(button_add);
+    gtk_widget_show(button_clear);
+    gtk_widget_show(button_hide_show);
+
+    /* The interface is completely set up so we show the window and
+     * enter the gtk_main loop.
+     */
+    gtk_widget_show(window);
+    gtk_main();
+    
+    return 0;
+}
+
+/* User clicked the "Add List" button. */
+void button_add_clicked( GtkWidget *button, gpointer data)
+{
+    int                indx;
+
+    /* Something silly to add to the list. 4 rows of 2 columns each */
+    gchar      *drink[4][2] = {{"Milk", "3 Oz"},
+                              {"Water", "6 l"},
+                              {"Carrots", "2"},
+                              {"Snakes", "55"}};
+
+    /* Here we do the actual adding of the text. It's done once for
+     * each row.
+     */
+    for( indx=0; indx < 4; indx++)
+       gtk_clist_append( (GtkCList*) data, drink[indx]);
+
+    return;
+}
+
+/* User clicked the "Clear List" button. */
+void button_clear_clicked( GtkWidget *button, gpointer data)
+{
+    /* Clear the list using gtk_clist_clear. This is much faster than
+     * calling gtk_clist_remove once for each row.
+     */
+    gtk_clist_clear((GtkCList*) data);
+
+    return;
+}
+
+/* The user clicked the "Hide/Show titles" button. */
+void button_hide_show_clicked( GtkWidget *button, gpointer data)
+{
+    /* Just a flag to remember the status. 0 = currently visible */
+    static short int flag = 0;
+
+    if (flag == 0)
+    {
+        /* Hide the titles and set the flag to 1 */
+       gtk_clist_column_titles_hide((GtkCList*) data);
+       flag++;
+    }
+    else
+    {
+        /* Show the titles and reset flag to 0 */
+       gtk_clist_column_titles_show((GtkCList*) data);
+       flag--;
+    }
+
+    return;
+}
+
+/* If we come here, then the user has selected a row in the list. */
+void selection_made( GtkWidget *clist, gint row, gint column,
+                    GdkEventButton *event, gpointer data)
+{
+    gchar      *text;
+
+    /* Get the text that is stored in the selected row and column
+     * which was clicked in. We will receive it as a pointer in the
+     * argument text.
+     */
+    gtk_clist_get_text(GTK_CLIST(clist), row, column, &text);
+
+    /* Just prints some information about the selected row */
+    g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text);
+
+    return;
+}
+/* example-end */